//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.luaj.vm2;

import android.content.res.AssetManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Build.VERSION;
import androidx.collection.LongSparseArray;
import com.immomo.mlncore.MLNCore;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.luaj.vm2.exception.InvokeError;
import org.luaj.vm2.exception.UndumpError;
import org.luaj.vm2.utils.IGlobalsUserdata;
import org.luaj.vm2.utils.LuaApiUsed;
import org.luaj.vm2.utils.NativeLog;
import org.luaj.vm2.utils.OnEmptyMethodCalledListener;
import org.luaj.vm2.utils.ResourceFinder;
import org.luaj.vm2.utils.SignatureUtils;

@LuaApiUsed
public final class Globals extends LuaTable {
  public static final int LUAC_VERSION = 83;
  public static final String LUAC_VERSION_STR = "5.2.4";
  public static final int LUA_OK = 0;
  public static final int LUA_YIELD = 1;
  public static final int LUA_ERRRUN = 2;
  public static final int LUA_ERRSYNTAX = 3;
  public static final int LUA_ERRMEM = 4;
  public static final int LUA_ERRGCMM = 5;
  public static final int LUA_ERRERR = 6;
  public static final int LUA_ERRINJAVA = -1;
  public static final int LUA_CALLING = 100;
  public static final char STATISTIC_BRIDGE = '\u0001';
  public static final char STATISTIC_REQUIRE = '\u0002';
  private static boolean init;
  private static boolean is32bit;
  private static final int JUST_INIT = -2147483648;
  private static long LUA_GC_OFFSET = 10000L;
  private static int LUA_GC_NUM_VALUES = 100;
  static final long GLOBALS_INDEX = -1L;
  long L_State;
  final long parent_L_State;
  long calledFunction = 0L;
  private int state = -2147483648;
  private String errorMsg = null;
  private Throwable error = null;
  private StringBuilder requireErrorMsg = null;
  private ResourceFinder resourceFinder;
  private Set<ResourceFinder> resourceFinders;
  private final HashMap<Class, String> luaClassNameMap;
  private IGlobalsUserdata javaUserdata;
  private List<Globals.OnDestroyListener> onDestroyListeners;
  private boolean debuggable;
  private boolean debugOpened;
  private Thread mainThread = Thread.currentThread();
  Handler handler;
  final UserdataCache userdataCache = new UserdataCache();
  private String basePath;
  private String soPath;
  private boolean isGlobal;
  private long lastGcTime = 0L;
  private boolean inGC = false;
  private int destroyedValues = 0;
  private boolean running = false;
  private final String TAG;
  private static LongSparseArray<Globals> cache = new LongSparseArray();
  private static LongSparseArray<Globals> g_cahce = new LongSparseArray();
  private static OnEmptyMethodCalledListener onEmptyMethodCalledListener;
  private static char statisticsStatus;
  private static final int DESTROYED = -2;
  private static final int NONE_LOOP = -3;
  private static final int SUCCESS = 0;

  private Globals(long L_State, long parent_L_State) {
    super(-1L);
    if (Looper.myLooper() != null) {
      this.handler = new Handler();
    }

    this.L_State = L_State;
    this.luaClassNameMap = new HashMap();
    this.parent_L_State = parent_L_State;
    this.TAG = "tag_" + this.hashCode();
  }

  public static boolean isInit() {
    if (!init) {
      try {
        is32bit = LuaCApi.is32bit();
        LuaCApi._setAndroidVersion(VERSION.SDK_INT);
        init = true;
      } catch (Throwable var1) {
        init = false;
      }
    }

    return init;
  }

  /** @deprecated */
  @Deprecated
  public static boolean isIs32bit() {
    return is32bit;
  }

  public static boolean is32bit() {
    return is32bit;
  }

  public static void setStatistic(char status) {
    if (status == 1 || status == 2 || status == 3 || status == 0) {
      statisticsStatus = status;
      LuaCApi._setStatisticsOpen(statisticsStatus != 0);
    }
  }

  public static void addStatisticStatus(char status) {
    if (status == 1 || status == 2) {
      if (statisticsStatus == 0) {
        LuaCApi._setStatisticsOpen(true);
      }

      statisticsStatus |= status;
    }
  }

  public static boolean isOpenStatistics() {
    return (statisticsStatus & 1) == 1 || (statisticsStatus & 2) == 2;
  }

  public static void notifyStatisticsCallback() {
    if ((statisticsStatus & 1) == 1) {
      LuaCApi._notifyStatisticsCallback();
    }

    if ((statisticsStatus & 2) == 2) {
      LuaCApi._notifyRequireCallback();
    }

  }

  public static void tryFullGc(int num) {
    if (num != 0) {
      long now = System.currentTimeMillis();
      int i = 0;

      for(int l = cache.size(); i < l; ++i) {
        final Globals g = (Globals)cache.valueAt(i);
        if (g.canGc(now)) {
          --num;
          g.post(new Runnable() {
            public void run() {
              g.gc();
            }
          });
          if (num == 0) {
            return;
          }
        }
      }

    }
  }

  public static boolean isENFile(String p) {
    return LuaCApi._isSAESFile(p);
  }

  public static void openSAES(boolean open) {
    LuaCApi._openSAES(open);
  }

  public static void setAssetManagerForNative(AssetManager am) {
    LuaCApi._setAssetManager(am);
  }

  public static Globals createLState(boolean debuggable) {
    long vmPointer = LuaCApi._createLState(debuggable);
    Globals g = new Globals(vmPointer, 0L);
    g.setSoPath(LuaConfigs.soPath);
    g.debuggable = debuggable;
    saveGlobals(g);
    return g;
  }

  public static void preRegisterEmptyMethods(String... methods) {
    LuaCApi._preRegisterEmptyMethods(methods);
  }

  public static void preRegisterUserdata(String clz, String... methods) {
    LuaCApi._preRegisterUD(clz, methods);
  }

  public static void preRegisterStatic(String clz, String... methods) {
    LuaCApi._preRegisterStatic(clz, methods);
  }

  private static void saveGlobals(Globals g) {
    if (g.isGlobal) {
      g_cahce.put(g.L_State, g);
    } else {
      cache.put(g.L_State, g);
    }

  }

  @LuaApiUsed
  static void __onNativeCreateGlobals(long p_vm, long vm, boolean debuggable) {
    Globals g = new Globals(vm, p_vm);
    g.debuggable = debuggable;
    if (p_vm == 0L) {
      g.isGlobal = true;
      g.setBasePath(LuaConfigs.soPath, false);
      addAllPathRFFromGlobals(g);
    } else {
      Globals parent = getGlobalsByLState(p_vm);
      g.setJavaUserdata(parent.javaUserdata);
      g.setBasePath(parent.basePath, false);
      g.setSoPath(parent.soPath);
      g.setResourceFinder(parent.resourceFinder);
      if (parent.resourceFinders != null) {
        g.resourceFinders = new HashSet(parent.resourceFinders);
      }
    }

    saveGlobals(g);
    MLNCore.onNativeCreateGlobals(g, p_vm == 0L);
  }

  @LuaApiUsed
  static void __onGlobalsDestroyInNative(long vm) {
    Globals globals = null;
    int index = cache.indexOfKey(vm);
    if (index >= 0) {
      globals = (Globals)cache.valueAt(index);
      cache.removeAt(index);
    } else {
      index = g_cahce.indexOfKey(vm);
      if (index > 0) {
        globals = (Globals)g_cahce.valueAt(index);
        g_cahce.removeAt(index);
      }
    }

    if (globals != null) {
      globals.destroy();
    }

  }

  public static Globals getGlobalsByLState(long state) {
    Globals g = (Globals)cache.get(state);
    if (g == null) {
      g = (Globals)g_cahce.get(state);
    }

    return g;
  }

  public static String debugGlobalsPointers() {
    int count = cache.size();
    StringBuilder sb = new StringBuilder("normal globals pointers:[");

    int i;
    long p;
    for(i = 0; i < count; ++i) {
      p = cache.keyAt(i);
      if (i == 0) {
        sb.append(Long.toHexString(p));
      } else {
        sb.append(',').append(Long.toHexString(p));
      }
    }

    sb.append(']').append("\nspecial globals pointers:[");
    count = g_cahce.size();

    for(i = 0; i < count; ++i) {
      p = g_cahce.keyAt(i);
      if (i == 0) {
        sb.append(Long.toHexString(p));
      } else {
        sb.append(',').append(Long.toHexString(p));
      }
    }

    return sb.append(']').toString();
  }

  public static int getLuaVmSize() {
    return cache.size() + g_cahce.size();
  }

  public static long getAllLVMMemUse() {
    return LuaCApi._allLvmMemUse();
  }

  public static void logMemoryLeakInfo() {
    LuaCApi._logMemoryInfo();
  }

  public static void setGcOffset(int offset) {
    LuaCApi._setGcOffset(offset);
  }

  public static void setLuaGcOffset(long ms) {
    LUA_GC_OFFSET = ms;
  }

  public static void setNeedDestroyNumber(int n) {
    LUA_GC_NUM_VALUES = n;
  }

  public static void setDatabasePath(String path) {
    if (!(new File(path)).exists()) {
      throw new IllegalStateException(path + " is not exists!");
    } else {
      LuaCApi._setDatabasePath(path);
    }
  }

  public final void openDebug() {
    if (!this.debuggable) {
      LuaCApi._openDebug(this.L_State);
      this.debuggable = true;
    }

  }

  public final boolean isIsolate() {
    return this.parent_L_State != 0L;
  }

  public final void setBasePath(String basePath, boolean autoSave) {
    this.checkDestroy();
    this.basePath = basePath == null ? "" : basePath;
    LuaCApi._setBasePath(this.L_State, this.basePath, autoSave);
  }

  public final void setSoPath(String path) {
    if (path != null) {
      this.checkDestroy();
      this.soPath = path;
      LuaCApi._setSoPath(this.L_State, path);
    }
  }

  public final boolean startDebug(byte[] debug, String ip, int port) {
    this.checkDestroy();
    if (this.debugOpened) {
      return true;
    } else {
      if (!this.debuggable) {
        this.openDebug();
      }

      try {
        this.state = LuaCApi._startDebug(this.L_State, debug, ip, port);
      } catch (Throwable var5) {
        this.error = var5;
        this.errorMsg = var5.getMessage();
        this.state = -1;
      }

      this.debugOpened = this.state == 0;
      return this.debugOpened;
    }
  }

  public final boolean loadString(String chunkName, String lua) {
    return this.loadData(chunkName, lua.getBytes());
  }

  public final boolean loadData(String chunkName, byte[] data) {
    this.checkDestroy();

    try {
      this.state = LuaCApi._loadData(this.L_State, chunkName, data);
    } catch (Throwable var4) {
      this.error = var4;
      this.errorMsg = var4.getMessage();
      this.state = -1;
    }

    return this.state == 0;
  }

  public final boolean loadFile(String path, String chunkName) {
    this.checkDestroy();

    try {
      this.state = LuaCApi._loadFile(this.L_State, path, chunkName);
    } catch (Throwable var4) {
      this.error = var4;
      this.errorMsg = var4.getMessage();
      this.state = -1;
    }

    return this.state == 0;
  }

  public final boolean loadAssetsFile(String path, String chunkName) {
    this.checkDestroy();

    try {
      this.state = LuaCApi._loadAssetsFile(this.L_State, path, chunkName);
    } catch (Throwable var4) {
      this.error = var4;
      this.errorMsg = var4.getMessage();
      this.state = -1;
    }

    return this.state == 0;
  }

  public final void preloadData(String chunkName, byte[] data) throws UndumpError {
    this.checkDestroy();
    LuaCApi._preloadData(this.L_State, chunkName, data);
  }

  public final void preloadFile(String chunkName, String path) throws UndumpError {
    this.checkDestroy();
    LuaCApi._preloadFile(this.L_State, chunkName, path);
  }

  public final int preloadAssetsAndSave(String chunkName, String path, String savePath) throws UndumpError {
    this.checkDestroy();
    File parent = (new File(savePath)).getParentFile();
    return !parent.exists() && !parent.mkdirs() ? -3 : LuaCApi._preloadAssetsAndSave(this.L_State, chunkName, path, savePath);
  }

  public final void preloadAssets(String chunkName, String path) throws UndumpError {
    this.checkDestroy();
    LuaCApi._preloadAssets(this.L_State, chunkName, path);
  }

  public final boolean require(String path) throws InvokeError {
    this.checkDestroy();
    return LuaCApi._require(this.L_State, path) == 0;
  }

  public final boolean setMainEntryFromPreload(String chunkname) {
    this.checkDestroy();
    if (LuaCApi._setMainEntryFromPreload(this.L_State, chunkname)) {
      this.state = 0;
      return true;
    } else {
      this.state = -404;
      this.errorMsg = "Did not find " + chunkname + " module from _preload table";
      this.error = new Exception(this.errorMsg);
      return false;
    }
  }

  public final boolean callLoadedData() {
    this.checkDestroy();
    if (this.state != 0) {
      if (this.state == -2147483648) {
        throw new IllegalStateException("Lua script is not loaded!");
      } else {
        throw new IllegalStateException("state of loading lua script is not ok, code: " + this.state);
      }
    } else {
      try {
        this.state = 100;
        this.state = LuaCApi._doLoadedData(this.L_State);
      } catch (Throwable var2) {
        this.error = var2;
        this.state = -1;
        MLNCore.hookLuaError(var2, this);
        this.errorMsg = var2.getMessage();
      }

      return this.state == 0;
    }
  }

  public final LuaValue[] callLoadedDataAndGetResult() throws IllegalStateException, InvokeError {
    this.checkDestroy();
    if (this.state != 0) {
      if (this.state == -2147483648) {
        throw new IllegalStateException("Lua script is not loaded!");
      } else {
        throw new IllegalStateException("state of loading lua script is not ok, code: " + this.state);
      }
    } else {
      this.state = 100;
      LuaValue[] ret = LuaCApi._doLoadedDataAndGetResult(this.L_State);
      this.state = 0;
      return ret;
    }
  }

  public final int getState() {
    return this.state;
  }

  public final String getErrorMsg() {
    return this.errorMsg;
  }

  public final Throwable getError() {
    return this.error;
  }

  public final void registerAllStaticClass(String[] lcns, String[] lpcns, String[] jcns) {
    this.checkDestroy();
    int len = lcns.length;
    if (len == lpcns.length && len == jcns.length) {
      LuaCApi._registerAllStaticClass(this.L_State, lcns, lpcns, jcns);
    } else {
      throw new IllegalArgumentException("lcns lpcns jcns must have same length");
    }
  }

  public final void registerAllUserdata(String[] lcns, String[] lpcns, String[] jcns, boolean[] lazy) throws RuntimeException {
    this.checkDestroy();
    int len = lcns.length;
    if (len == lpcns.length && len == jcns.length) {
      LuaCApi._registerAllUserdata(this.L_State, lcns, lpcns, jcns, lazy);
    } else {
      throw new IllegalArgumentException("lcns lpcns jcns must have same length");
    }
  }

  public final void registerJavaMetatable(Class clz, String name) {
    LuaCApi._registerJavaMetatable(this.L_State, SignatureUtils.getClassName(clz), name);
  }

  public final void registerNumberEnum(String lcn, String[] keys, double[] values) {
    this.checkDestroy();
    if (keys != null && values != null) {
      if (keys.length != values.length) {
        throw new IllegalArgumentException("keys and values must have same length!");
      } else {
        LuaCApi._registerNumberEnum(this.L_State, lcn, keys, values);
      }
    }
  }

  public final void registerStringEnum(String lcn, String[] keys, String[] values) {
    this.checkDestroy();
    if (keys != null && values != null) {
      if (keys.length != values.length) {
        throw new IllegalArgumentException("keys and values must have same length!");
      } else {
        LuaCApi._registerStringEnum(this.L_State, lcn, keys, values);
      }
    }
  }

  private static void addAllPathRFFromGlobals(Globals gg) {
    int i = 0;

    for(int l = cache.size(); i < l; ++i) {
      Globals g = (Globals)cache.valueAt(i);
      Set<ResourceFinder> grfs = g.resourceFinders;
      if (grfs != null) {
        gg.resourceFinders.addAll(grfs);
        if (g.resourceFinder != null) {
          gg.resourceFinders.add(g.resourceFinder);
        }
      }
    }

  }

  private static void addRFToGlobals(ResourceFinder rf) {
    int i = 0;

    for(int l = g_cahce.size(); i < l; ++i) {
      ((Globals)g_cahce.valueAt(i)).resourceFinders.add(rf);
    }

  }

  public void setResourceFinder(ResourceFinder rf) {
    this.resourceFinder = rf;
    if (!this.isGlobal) {
      addRFToGlobals(rf);
    }

  }

  public void setResourceFinders(Collection<ResourceFinder> rfs) {
    this.resourceFinders = new HashSet(rfs);
  }

  public void addResourceFinder(ResourceFinder rf) {
    if (this.resourceFinders == null) {
      this.resourceFinders = new HashSet();
    }

    this.resourceFinders.add(rf);
    if (!this.isGlobal) {
      addRFToGlobals(rf);
    }

  }

  public void clearResourceFinder() {
    if (this.resourceFinders != null) {
      this.resourceFinders.clear();
    }

  }

  public final boolean isDebugOpened() {
    return this.debugOpened;
  }

  public final void setRunning(boolean running) {
    this.running = running;
  }

  public final boolean isRunning() {
    return this.running;
  }

  public final long getLVMMemUse() {
    return LuaCApi._lvmMemUse(this.L_State);
  }

  public final LuaValue[] dump() {
    this.checkDestroy();
    return LuaCApi._dumpStack(this.L_State);
  }

  public final String luaTraceBack() {
    this.checkDestroy();
    return LuaCApi._traceback(this.L_State);
  }

  public final boolean isInLuaFunction() {
    return this.state == 100 || this.calledFunction > 0L;
  }

  public final boolean post(Runnable r) {
    return this.handler != null ? this.handler.post(r) : false;
  }

  public final boolean postDelayed(Runnable r, long ms) {
    Message message = Message.obtain(this.handler, r);
    message.obj = this.TAG;
    return this.handler.sendMessageDelayed(message, ms);
  }

  public final boolean isDestroyed() {
    return this.destroyed || this.L_State == 0L;
  }

  public final void destroy() {
    this.checkMainThread();
    if (this.isDestroyed() || !MLNCore.DEBUG || this.state != 100 && this.calledFunction <= 0L) {
      if (!this.isDestroyed()) {
        MLNCore.onGlobalsDestroy(this);
        if (this.onDestroyListeners != null) {
          Iterator var1 = this.onDestroyListeners.iterator();

          while(var1.hasNext()) {
            Globals.OnDestroyListener l = (Globals.OnDestroyListener)var1.next();
            l.onDestroy(this);
          }

          this.onDestroyListeners.clear();
        }

        this.destroyed = true;
        long pointer = this.L_State;
        this.L_State = 0L;
        if (this.handler != null) {
          this.handler.removeCallbacksAndMessages(this.TAG);
        }

        if (!this.isIsolate()) {
          LuaCApi._close(pointer);
        }

        this.userdataCache.onDestroy();
        if (this.javaUserdata != null) {
          this.javaUserdata.onGlobalsDestroy(this);
        }

        this.javaUserdata = null;
        NativeLog.release(pointer);
        cache.remove(pointer);
        g_cahce.remove(pointer);
        this.luaClassNameMap.clear();
        this.resourceFinder = null;
        if (this.resourceFinders != null) {
          this.resourceFinders.clear();
        }

      }
    } else {
      throw new IllegalStateException("throw in debug mode, cannot destroy lua vm when lua function is calling!");
    }
  }

  public final Object createUserdataAndSet(String key, String luaClassName, LuaValue... params) throws RuntimeException {
    this.checkDestroy();
    return LuaCApi._createUserdataAndSet(this.L_State, key, luaClassName, params);
  }

  public final long getL_State() {
    return this.L_State;
  }

  public final void setJavaUserdata(IGlobalsUserdata userdata) {
    this.javaUserdata = userdata;
    NativeLog.register(this.L_State, userdata);
  }

  public final IGlobalsUserdata getJavaUserdata() {
    return this.javaUserdata;
  }

  public final String getLuaClassName(Class c) {
    return (String)this.luaClassNameMap.get(c);
  }

  public final void putLuaClassName(Class<? extends LuaUserdata> clz, String lcn) {
    this.luaClassNameMap.put(clz, lcn);
  }

  public final void putLuaClassName(Map<Class, String> other) {
    this.luaClassNameMap.putAll(other);
  }

  public synchronized void addOnDestroyListener(Globals.OnDestroyListener l) {
    if (l != null) {
      if (this.onDestroyListeners == null) {
        this.onDestroyListeners = new ArrayList();
      }

      this.onDestroyListeners.add(l);
    }
  }

  public synchronized void removeOnDestroyListener(Globals.OnDestroyListener l) {
    if (this.onDestroyListeners != null) {
      this.onDestroyListeners.remove(l);
    }

  }

  public static void setOnEmptyMethodCalledListener(OnEmptyMethodCalledListener listener) {
    onEmptyMethodCalledListener = listener;
  }

  public static String findLuaParentClass(Class c, Map<Class, String> luaClassNameMap) {
    for(Class p = c.getSuperclass(); p != null && p != Object.class && p != JavaUserdata.class && p != LuaUserdata.class; p = p.getSuperclass()) {
      String s = (String)luaClassNameMap.get(p);
      if (s != null) {
        return s;
      }
    }

    return null;
  }

  boolean hasLooper() {
    return this.handler != null;
  }

  boolean isMainThread() {
    return true;
  }

  void checkMainThread() {
    if (!this.isMainThread()) {
      throw new IllegalStateException("must called in main thread: " + this.globals.mainThread);
    }
  }

  long globalsIndex() {
    return -1L;
  }

  boolean removeStack(final LuaValue value) {
    if (value instanceof Globals) {
      return false;
    } else {
      this.checkDestroy();
      final long key = value.nativeGlobalKey();
      if (key != 0L && key != -1L) {
        if (this.isMainThread() && this.canDestroySync()) {
          boolean destroy = LuaCApi._removeNativeValue(this.L_State, key, value.type()) <= 0;
          if (destroy) {
            ++this.destroyedValues;
            this.gc();
          }

          return destroy;
        } else {
          if (this.handler != null) {
            this.handler.post(new Runnable() {
              public void run() {
                if (!Globals.this.isDestroyed()) {
                  value.destroyed = LuaCApi._removeNativeValue(Globals.this.L_State, key, value.type()) <= 0;
                  if (value.destroyed) {
                    Globals.this.destroyedValues++;
                    Globals.this.gc();
                  }

                }
              }
            });
          }

          return true;
        }
      } else {
        return true;
      }
    }
  }

  private boolean canDestroySync() {
    return !this.inGC || System.currentTimeMillis() - this.lastGcTime < 10L;
  }

  private boolean canGc(long time) {
    if (!this.inGC && this.state != -2147483648 && !this.isDestroyed()) {
      return time - this.lastGcTime > LUA_GC_OFFSET;
    } else {
      return false;
    }
  }

  private boolean gc() {
    long now = System.currentTimeMillis();
    if (this.canGc(now) && this.destroyedValues > LUA_GC_NUM_VALUES) {
      this.destroyedValues = 0;
      this.lastGcTime = now;
      this.inGC = true;
      LuaCApi._lgc(this.L_State);
      this.lastGcTime = System.currentTimeMillis();
      MLNCore.luaGcCast(this, this.lastGcTime - now);
      this.inGC = false;
      return true;
    } else {
      return false;
    }
  }

  public final void set(int index, LuaValue value) {
    this.unsupported();
  }

  public final void set(int index, double num) {
    this.unsupported();
  }

  public final void set(int index, boolean b) {
    this.unsupported();
  }

  public final void set(int index, String s) {
    this.unsupported();
  }

  public final void set(int index, Class<?> clz, Method method) {
    this.unsupported();
  }

  public final LuaValue get(int index) {
    this.unsupported();
    return null;
  }

  private void unsupported() {
    throw new UnsupportedOperationException("global is not support set/get a number key!");
  }

  @LuaApiUsed
  private static Object __onLuaRequire(long L, String name) {
    return getGlobalsByLState(L).onRequire(name);
  }

  @LuaApiUsed
  private static String __getRequireError(long L) {
    return getGlobalsByLState(L).getRequireErrorMsg();
  }

  @LuaApiUsed
  private static void __onLuaGC(long L) {
    System.gc();
  }

  @LuaApiUsed
  private static void __onEmptyMethodCall(long L, String clz, String methodName) {
    if (onEmptyMethodCalledListener != null) {
      Globals g = getGlobalsByLState(L);
      if (g != null) {
        onEmptyMethodCalledListener.onCalled(g, clz, methodName);
      }
    }

  }

  @LuaApiUsed
  private static int __postCallback(final long L, final long method, final long args) {
    final Globals g = getGlobalsByLState(L);
    if (g != null && !g.isDestroyed()) {
      if (!g.hasLooper()) {
        return -3;
      } else {
        g.handler.post(new Runnable() {
          public void run() {
            long l = g.isDestroyed() ? 0L : L;
            LuaCApi._callMethod(l, method, args);
          }
        });
        return 0;
      }
    } else {
      return -2;
    }
  }

  private Object onRequire(String name) {
    if (this.requireErrorMsg != null) {
      this.requireErrorMsg.setLength(0);
    }

    if (this.resourceFinder == null && this.resourceFinders == null) {
      if (this.requireErrorMsg == null) {
        this.requireErrorMsg = new StringBuilder();
      }

      this.requireErrorMsg.append("\n\t\tno resource finder set in java!");
      return null;
    } else {
      Object ret = findResource(this.resourceFinder, name);
      if (ret != null) {
        return ret;
      } else {
        this.combineErrorMessage(this.resourceFinder);
        if (this.resourceFinders != null) {
          Iterator var3 = this.resourceFinders.iterator();

          while(var3.hasNext()) {
            ResourceFinder rf = (ResourceFinder)var3.next();
            ret = findResource(rf, name);
            if (ret != null) {
              return ret;
            }

            this.combineErrorMessage(rf);
          }
        }

        return null;
      }
    }
  }

  private String getRequireErrorMsg() {
    return this.requireErrorMsg != null && this.requireErrorMsg.length() != 0 ? this.requireErrorMsg.toString() : null;
  }

  private void combineErrorMessage(ResourceFinder rf) {
    if (rf != null) {
      String error = rf.getError();
      if (error != null && error.length() != 0) {
        if (this.requireErrorMsg == null) {
          this.requireErrorMsg = new StringBuilder();
        }

        this.requireErrorMsg.append("\n\t\t").append(error);
      }
    }
  }

  @LuaApiUsed
  static Object __getUserdata(long L, long id) {
    Globals g = getGlobalsByLState(L);
    return g == null ? null : g.userdataCache.get(id);
  }

  private void checkDestroy() {
    if (this.isDestroyed()) {
      throw new IllegalStateException("this lua vm is destroyed!");
    }
  }

  private static Object findResource(ResourceFinder rf, String name) {
    if (rf != null) {
      name = rf.preCompress(name);
      String path = rf.findPath(name);
      if (path != null) {
        return path;
      }

      byte[] data = rf.getContent(name);
      if (data != null) {
        rf.afterContentUse(name);
        return data;
      }
    }

    return null;
  }

  public String toString() {
    return "Globals#" + this.hashCode();
  }

  public int hashCode() {
    return (int)(this.L_State ^ this.L_State >>> 32);
  }

  public boolean equals(Object o) {
    return o == this;
  }

  public interface OnDestroyListener {
    void onDestroy(Globals var1);
  }
}
